home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / dlink / reloc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-09-09  |  24.0 KB  |  862 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6.  
  7. /*
  8.  *  RELOC.C
  9.  *
  10.  *
  11.  *  hunk usually points to the hunk needing parts of itself
  12.  *  relocated.
  13.  *
  14.  *  HL points to the HunkListNode that the data is actually defined
  15.  *     in.
  16.  *
  17.  *  HX points to the HunkListNode... the final HunkNo that we will
  18.  *     use in the relocation list.
  19.  */
  20.  
  21. /*
  22. **      $Filename: reloc.c $
  23. **      $Author: dice $
  24. **      $Revision: 30.6 $
  25. **      $Date: 1994/08/04 04:50:55 $
  26. **      $Log: reloc.c,v $
  27.  * Revision 30.6  1994/08/04  04:50:55  dice
  28.  * .
  29.  *
  30.  * Revision 30.5  1994/06/13  18:38:37  dice
  31.  * byte ordering portability
  32.  *
  33.  * Revision 30.0  1994/06/10  18:05:40  dice
  34.  * .
  35.  *
  36.  * Revision 1.2  1993/10/13  19:48:08  jtoebes
  37.  * Fix BUG01125 - Enforce hit in Dlink.
  38.  *
  39. **/
  40.  
  41. #include "defs.h"
  42.  
  43. Prototype void    copy_reloc(long *, long *, long, long);
  44. Prototype void    ScanHunkReloc32(Hunk *, long);
  45. Prototype void    ScanHunkReloc8_16(ulong *, Hunk *, long);
  46. Prototype void    ScanHunkReloc8(Hunk *);
  47. Prototype void    ScanHunkReloc16(Hunk *);
  48. Prototype void    ScanHunkRelocD16(Hunk *);
  49. Prototype int    ScanHunkExt(Hunk *, long);
  50. Prototype int    HunkExtSymCK(Hunk *, ubyte, ulong, ulong *);
  51. Prototype int    HunkExtSymIN(Hunk *, ubyte, ulong, ulong *);
  52. Prototype int    HunkExtSymCNT(Hunk *, ubyte, ulong, ulong *);
  53. Prototype int    HunkExtSymRUN(Hunk *, ubyte, ulong, ulong *);
  54. Prototype int    HunkExtSymComResolve(Hunk *, ubyte, ulong, ulong *);
  55. Prototype void    IllegalHunk(short, Hunk *);
  56.  
  57. /*
  58.  *  Copy relocation information to the final relocation array, modifying it
  59.  *  as we go along.  When hunks are combined together the relocation info
  60.  *  for them must also be modified to point to the new location of the hunk
  61.  *  in the section.
  62.  */
  63.  
  64. void
  65. copy_reloc(s, d, nlw, off)
  66. long *s;
  67. long *d;
  68. long nlw;
  69. long off;
  70. {
  71.     if (off == 0) {
  72.     movmem(s, d, nlw * 4);
  73.     return;
  74.     }
  75.     while (nlw--) {
  76.     *d = ToMsbOrder(FromMsbOrder(*s) + off);
  77.     ++s;
  78.     ++d;
  79.     }
  80. }
  81.  
  82. void
  83. ScanHunkReloc32(hunk, copy)
  84. Hunk *hunk;
  85. long copy;
  86. {
  87.     ulong *scan = hunk->Reloc32;
  88.  
  89.     if (scan == NULL)
  90.     return;
  91.  
  92.     Assert(hunk->Module);
  93.  
  94.     while (FromMsbOrder(*scan)) {
  95.     Hunk *destHunk = hunk->Module->Hunks[FromMsbOrder(scan[1])];
  96.     long hunkNo;
  97.  
  98.     if ((ulong)FromMsbOrder(scan[1]) >= hunk->Module->NumHunks)
  99.         IllegalHunk(EF_FATAL, NULL);
  100.     if (destHunk->Node.ln_Type != NT_BSS && destHunk->Node.ln_Type != NT_CODE && destHunk->Node.ln_Type != NT_DATA)
  101.         IllegalHunk(EF_FATAL, destHunk);
  102.     if (PIOpt)
  103.         cerror(EERROR_RELOC32_ILLEGAL_PI, hunk->Module->Node.ln_Name, hunk->Node.ln_Name);
  104.     if (ResOpt && !AbsWordOpt && (destHunk->Node.ln_Type == NT_BSS || destHunk->Node.ln_Type == NT_DATA))
  105.         cerror(EERROR_RELOC32_DATABSS_RES, hunk->Module->Node.ln_Name, hunk->Node.ln_Name);
  106.  
  107.     hunkNo = destHunk->HX->FinalHunkNo;
  108.     if (hunkNo < 0 || hunkNo >= NumExtHunks)
  109.         cerror(EFATAL_RELOCSCAN_HUNK_RANGE, hunkNo, NumExtHunks);
  110.     if (copy == 0) {            /*  just count # of relocs */
  111.         hunk->HL->CntReloc32[hunkNo] += FromMsbOrder(*scan);
  112.     } else {                /*  actually copy stuff    */
  113.         {
  114.         long bas = hunk->HL->CpyReloc32[hunkNo];
  115.         long fnl = bas + FromMsbOrder(*scan);
  116.         if (fnl > hunk->HL->CntReloc32[hunkNo])
  117.             cerror(EFATAL_RELOC_NOEXIST_HUNK, fnl, hunk->HL->CntReloc32[hunkNo]);
  118.         copy_reloc(scan + 2, hunk->HL->ExtReloc32[hunkNo] + bas, FromMsbOrder(*scan), hunk->Offset);
  119.         hunk->HL->CpyReloc32[hunkNo] = fnl;
  120.         }
  121.  
  122.         /*
  123.          *    Handle fixing up the base offset.
  124.          */
  125.  
  126.         Assert(hunk->Module);
  127.  
  128.         if (FromMsbOrder(scan[0])) {
  129.         char *dbase = (char *)hunk->Data;
  130.         ulong dlen = hunk->Bytes;
  131.         Hunk *destHunk = hunk->Module->Hunks[FromMsbOrder(scan[1])];
  132.         long n;
  133.         long destOff;
  134.         ulong *newScan;
  135.  
  136.         if ((ulong)FromMsbOrder(scan[1]) >= hunk->Module->NumHunks)
  137.             IllegalHunk(EF_FATAL, NULL);
  138.         if (destHunk->Node.ln_Type != NT_BSS && destHunk->Node.ln_Type != NT_CODE && destHunk->Node.ln_Type != NT_DATA)
  139.             IllegalHunk(EF_FATAL, destHunk);
  140.  
  141.         destOff = destHunk->Offset;
  142.         if (destHunk->HL != destHunk->HX)
  143.             destOff += destHunk->HX->FinalSize;
  144.  
  145.         if (hunk->Node.ln_Type == NT_BSS)
  146.             cerror(EFATAL_RELOC_BSS_ILLEGAL);
  147.  
  148.         newScan = scan + 2;    /*  base of offsets */
  149.         n = FromMsbOrder(*scan);/*  # of offsets    */
  150.  
  151.         while (n--) {
  152.             ulong doff = FromMsbOrder(*newScan);
  153.             long rval;
  154.  
  155.             dbprintf(2, ("mod --- reloc32 %s@%ld(%ld) to %s@%ld\n", HunkToStr(hunk), doff, FromMsbOrder(*(ulong *)(dbase + doff)), HunkToStr(destHunk), destOff));
  156.  
  157.             if (doff >= dlen)
  158.             cerror(EFATAL_RANGE_HUNK, doff, HunkToStr(hunk));
  159.             rval = destOff + FromMsbOrder(*(ulong *)(dbase + doff));
  160.             *(ulong *)(dbase + doff) = ToMsbOrder(rval);
  161.             ++newScan;
  162.         }
  163.         }
  164.     }
  165.     scan += FromMsbOrder(scan[0]) + 2;
  166.     }
  167. }
  168.  
  169. /*
  170.  *  This runs actual 8 and 16 bit PC relative relocations.
  171.  *     runs actual 16 bit DATA relative relocations
  172.  */
  173.  
  174. void
  175. ScanHunkReloc8_16(scan, hunk, bits)
  176. ulong *scan;
  177. Hunk *hunk;
  178. long bits;
  179. {
  180.     char *dbase;
  181.     long dlen;
  182.  
  183.     if (scan == NULL)
  184.     return;
  185.  
  186.     dbase = (char *)hunk->Data;
  187.     dlen = hunk->Bytes;
  188.  
  189.     Assert(hunk->Module);
  190.  
  191.     while (FromMsbOrder(*scan)) {
  192.     Hunk *destHunk = hunk->Module->Hunks[FromMsbOrder(scan[1])];
  193.     long hunkNo;
  194.     long n;
  195.     long destOff;
  196.     short absWord = 0;
  197.  
  198.     if ((ulong)FromMsbOrder(scan[1]) >= hunk->Module->NumHunks)
  199.         IllegalHunk(EF_FATAL, NULL);
  200.     if (destHunk->Node.ln_Type != NT_BSS && destHunk->Node.ln_Type != NT_CODE && destHunk->Node.ln_Type != NT_DATA)
  201.         IllegalHunk(EF_FATAL, destHunk);
  202.     hunkNo = destHunk->HX->FinalHunkNo;
  203.     if (hunkNo < 0 || hunkNo >= NumExtHunks)
  204.         cerror(EFATAL_RELOCSCAN_HUNK_RANGE, hunkNo, NumExtHunks);
  205.  
  206.     destOff = destHunk->Offset;
  207.     if (destHunk->HL != destHunk->HX)
  208.         destOff += destHunk->HX->FinalSize;
  209.  
  210.     /*
  211.      *  modify hunk->Data
  212.      */
  213.  
  214.     if (bits > 0) {     /*    PC-RELATIVE RELOCATION    */
  215.         if (hunk->Node.ln_Type == NT_BSS) {
  216.         cerror(EERROR_RELOCPCREL_BSS_ILLEGAL);
  217.         return;
  218.         }
  219.         if (hunk->HL != destHunk->HX) {
  220.         if (AbsWordOpt && hunk->Node.ln_Type == NT_CODE) {
  221.             absWord = 1;
  222.             dbprintf(0, ("Absolute Word Relocation"));
  223.         } else {
  224.             cerror(EERROR_RELOCPCREL_ILLEGAL,
  225.             hunk->Module->Node.ln_Name, hunk->Node.ln_Name,
  226.             destHunk->Module->Node.ln_Name, destHunk->Node.ln_Name
  227.             );
  228.             return;
  229.         }
  230.         }
  231.     } else {        /*    DATA BASE RELATIVE RELOCATION    */
  232.         if (destHunk->Node.ln_Type == NT_CODE) {
  233.         cerror(EERROR_RELOC_LABREL_CODE_ILL);
  234.         return;
  235.         }
  236.         /* XXX warning msg if not to same data segment! */
  237.     }
  238.  
  239.     n = FromMsbOrder(*scan);  /*    # of relocs        */
  240.     scan += 2;  /*    beginning of relocs */
  241.  
  242.     while (n--) {
  243.         ulong doff = FromMsbOrder(*scan); /* offset into this hunk's data */
  244.         long pcrel;
  245.  
  246.         if (doff >= dlen) {
  247.         cerror(EERROR_RANGE_HUNK, doff);
  248.         return;
  249.         }
  250.         switch(bits) {
  251.         case 8:
  252.         dbprintf(2, ("mod --- reloc08 %s@%ld(%ld) to %s\n", HunkToStr(hunk), doff, *(ubyte *)(dbase + doff), HunkToStr(destHunk)));
  253.         pcrel = (destOff + *(char *)(dbase + doff)) - (hunk->Offset + doff);
  254.         if (pcrel < -128 || pcrel > 127)
  255.             cerror(EERROR_RELOC8_RANGE, pcrel, HunkToStr(hunk));
  256.         *(ubyte *)(dbase + doff) = pcrel;
  257.         break;
  258.         case 16:
  259.         dbprintf(2, ("mod --- reloc16 %s@%ld(%ld) to %s\n", HunkToStr(hunk), doff, FromMsbOrderShort(*(short *)(dbase + doff)), HunkToStr(destHunk)));
  260.         if (absWord)
  261.             pcrel = (destOff + FromMsbOrderShort(*(short *)(dbase + doff))) + WordBaseAddr;
  262.         else
  263.             pcrel = (destOff + FromMsbOrderShort(*(short *)(dbase + doff))) - (hunk->Offset + doff);
  264.         if (pcrel < -32768 || pcrel > 32767)
  265.             cerror(EERROR_RELOC16_RANGE, pcrel, HunkToStr(hunk));
  266.         *(short *)(dbase + doff) = ToMsbOrderShort(pcrel);
  267.         break;
  268.         case -16:        /*    16 bit data relative    */
  269.         dbprintf(2, ("mod --- reloD16 %s@%ld(%ld) to %s\n", HunkToStr(hunk), doff, FromMsbOrderShort(*(short *)(dbase + doff)) - 32766, HunkToStr(destHunk)));
  270.         pcrel = (destOff + FromMsbOrderShort(*(short *)(dbase + doff))) - 32766;
  271.         if (pcrel < -32768 || pcrel > 32767)
  272.             cerror(EERROR_RELOC16_RANGE, pcrel, HunkToStr(hunk));
  273.         *(short *)(dbase + doff) = ToMsbOrderShort(pcrel);
  274.         break;
  275.         }
  276.         ++scan;
  277.     }
  278.     }
  279. }
  280.  
  281. void
  282. ScanHunkReloc8(hunk)
  283. Hunk *hunk;
  284. {
  285.     ScanHunkReloc8_16(hunk->Reloc8, hunk, 8);
  286. }
  287.  
  288. void
  289. ScanHunkReloc16(hunk)
  290. Hunk *hunk;
  291. {
  292.     ScanHunkReloc8_16(hunk->Reloc16, hunk, 16);
  293. }
  294.  
  295. void
  296. ScanHunkRelocD16(hunk)
  297. Hunk *hunk;
  298. {
  299.     ScanHunkReloc8_16(hunk->Reloc16D, hunk, -16);
  300. }
  301.  
  302.  
  303. /*
  304.  *                SYMBOLS
  305.  *        -----------------------------------------------------
  306.  */
  307.  
  308. /*
  309.  *  External Symbol Scan
  310.  *
  311.  *  Count / handle references from the external symbol table.  This functions
  312.  *  returns the sum of all subroutine calls.
  313.  */
  314.  
  315. int
  316. ScanHunkExt(hunk, cmd)
  317. Hunk *hunk;
  318. long cmd;
  319. {
  320.     ulong *scan = hunk->Ext;
  321.     ubyte type;
  322.     ulong len;
  323.     ulong result = 0;
  324.  
  325.     if (scan == NULL)
  326.     return(0);
  327.  
  328.     /*
  329.      *    scan symbol units for hunk.
  330.      */
  331.  
  332.     while (FromMsbOrder(*scan)) {
  333.     ulong *newScan;
  334.  
  335.  
  336.     type = FromMsbOrder(*scan) >> 24;
  337.     len  = FromMsbOrder(*scan) & 0x00FFFFFF;
  338.     ++scan;
  339.  
  340.     switch(cmd) {
  341.     case SCAN_RELOC_SYMCK:
  342.         result += HunkExtSymCK(hunk, type, len, scan);
  343.         break;
  344.     case SCAN_RELOC_SYMIN:
  345.         result += HunkExtSymIN(hunk, type, len, scan);
  346.         break;
  347.     case SCAN_RELOC_CNT:
  348.         result += HunkExtSymCNT(hunk, type, len, scan);
  349.         break;
  350.     case SCAN_RELOC_RUN:
  351.         result += HunkExtSymRUN(hunk, type, len, scan);
  352.         break;
  353.     case SCAN_RELOC_JUMP:
  354.         result += HunkExtSymJUMP(hunk, type, len, scan);
  355.         break;
  356.     case SCAN_COMMON_RESOLVE:
  357.         if (type == 130)
  358.         result += HunkExtSymComResolve(hunk, type, len, scan);
  359.         break;
  360.     }
  361.  
  362.     newScan = scan + len;        /*    skip symbol name    */
  363.  
  364.     switch(type) {
  365.     case 0:     /*  symbol table    */
  366.     case 1:     /*  exported reloc def    */
  367.     case 2:     /*  exported abs def    */
  368.     case 3:     /*  exported res lib def*/
  369.         scan = newScan + 1;
  370.         break;
  371.     case 130:    /*  common        */
  372.         scan = newScan + 1;
  373.         break;
  374.     case RESERVED_PCJMP_TYPE:
  375.     case 135:    /*  imported ref32-pc    */
  376.     case 129:    /*  imported ref32    */
  377.     case 131:    /*  imported ref16    */
  378.     case 132:    /*  imported ref8    */
  379.     case 134:    /*  imported ref16D    */
  380.         scan = newScan + FromMsbOrder(newScan[0]) + 1;
  381.         break;
  382.     default:
  383.         cerror(EERROR_UNKNOWN_SYM_TYPE, type, len, scan);
  384.         return(0);
  385.     }
  386.     }
  387.     return((long)result);
  388. }
  389.  
  390. /*
  391.  *  CK
  392.  *
  393.  *  This is called to check exported (xdef)d symbols in a library module
  394.  *  searching for undefined symbols to see if we have to include the library
  395.  *  or not.  It returns (1) if a previously undefined symbol is matched with
  396.  *  an xdef.
  397.  *
  398.  *  HunkListNode has not been created at this point, so hunk->HL is invalid
  399.  *  as well as hn.  Also, sym->Hunk may be NULL for linker ABS symbols.
  400.  *
  401.  *  COMMON symbols are references for this routine
  402.  */
  403.  
  404. int
  405. HunkExtSymCK(Hunk *hunk, ubyte type, ulong len, ulong *scan)
  406. {
  407.     Sym *sym;
  408.  
  409.     if (type == 1 || type == 2 || type == 3) {
  410.     if ((sym = FindSymbol(scan, len)) != NULL) {
  411.         if (sym->Type == 0)
  412.         return(1);
  413.     }
  414.     }
  415.     return(0);
  416. }
  417.  
  418. /*
  419.  *  IN
  420.  *
  421.  *  This is called to bring the ref'd and def'd symbols associated with a module
  422.  *  into the master symbol table.  This routine returns (1) If adding the
  423.  *  symbol creates a NEW undefined reference (to force another pass through
  424.  *  the library).
  425.  *
  426.  *  HunkListNode has not been created at this point, so hunk->HL is invalid
  427.  *  as well as hn
  428.  *
  429.  *  COMMON symbols are ignored for this routine
  430.  */
  431.  
  432. int
  433. HunkExtSymIN(Hunk *hunk, ubyte type, ulong len, ulong *scan)
  434. {
  435.     Sym *sym;
  436.  
  437.     if (type == 1 || type == 2 || type == 3) {        /*    def */
  438.     /*
  439.      *  Note that a def symbol may overide a common symbol
  440.      */
  441.  
  442.     if ((sym = FindSymbol(scan, len)) != NULL) {
  443.         /*
  444.          *    If duplicate def and both hunks are object modules or both
  445.          *    hunks are the *same* library then complain.
  446.          */
  447.  
  448.         if (sym->Hunk) {        /*    duplicate   */
  449.         Assert(sym->Hunk->Module);
  450.         Assert(hunk->Module);
  451.  
  452.         if (sym->Type == 130) {
  453.             /*
  454.              *    always overide a common symbol
  455.              */
  456.             SetSymbol(sym, hunk, FromMsbOrder(scan[len]), type);
  457.         } else if (sym->Hunk->Module->Node.ln_Type == NT_FTOBJ && hunk->Module->Node.ln_Type == NT_FTOBJ) {
  458.             cerror(EWARN_MULT_DEF_SYM, len*4, scan, sym->Hunk->Module->Node.ln_Name, hunk->Module->Node.ln_Name);
  459.         }
  460.         if (sym->Hunk->Module->Node.ln_Type == NT_FTLIB && hunk->Module->Node.ln_Type == NT_FTLIB && sym->Hunk->Module->FNode == hunk->Module->FNode)
  461.             cerror(EWARN_MULT_DEF_SYM_LIB, len*4, scan);
  462.         } else {            /*    first def   */
  463.         SetSymbol(sym, hunk, FromMsbOrder(scan[len]), type);
  464.         dbprintf(1, ("SetSym type %-3d value %-3d %.*s\n", type, sym->Value, sym->SymLen, sym->SymName));
  465.         }
  466.     } else {
  467.         CreateSymbol(scan, len, hunk, FromMsbOrder(scan[len]), type);
  468.     }
  469.     } else if (type == 129 || type == 131 || type == 132 || type == 134 || type == 135) {     /*  ref */
  470.     if ((sym = FindSymbol(scan, len)) != NULL) {
  471.         ++sym->Refs;            /*  def'd or undef'd    */
  472.     } else {
  473.         sym = CreateSymbol(scan, len, NULL, 0, 0);      /*  new undef'd         */
  474.         ++sym->Refs;
  475.         return(1);
  476.     }
  477.     } else if (type == 130) {
  478.     /*
  479.      *  A common symbol is ignored if it already exists, else it is
  480.      *  entered.
  481.      */
  482.  
  483.     if ((sym = FindSymbol(scan, len)) == NULL) {
  484.         CreateSymbol(scan, len, hunk, FromMsbOrder(scan[len]), type);
  485.         /*printf("Create common %d\n", type);*/
  486.     } else {
  487.         if (sym->Type == 0) {
  488.         SetSymbol(sym, hunk, FromMsbOrder(scan[len]), type);
  489.         /*printf("OVR common %d\n", type);*/
  490.         } else {
  491.         /*printf("Ignore common %d\n", type);*/
  492.         }
  493.     }
  494.     } else if (type != 0) {
  495.     cerror(EERROR_UNKNOWN_SYM_TYPE, type, len * 4, scan);
  496.     }
  497.     return(0);
  498. }
  499.  
  500. /*
  501.  *  COMMON_RESOLVE
  502.  *
  503.  *  This routine picks out unresolved common symbols and resolves them.
  504.  *  It returns a dummy 0.  Note that the passed hunk is ignored since
  505.  *  common variables overide later common variables, only sym->Hunk is
  506.  *  valid.
  507.  *
  508.  *  This routine is only called with type == 130
  509.  */
  510.  
  511. int
  512. HunkExtSymComResolve(Hunk *hunk, ubyte type, ulong len, ulong *scan)
  513. {
  514.     Sym *sym;
  515.     long size;
  516.  
  517.  
  518.     if ((sym = FindSymbol(scan, len)) != NULL) {
  519.     hunk = sym->Hunk;   /*    hunk symbol applies to    */
  520.  
  521.     if (sym->Type == 130) {
  522.         Assert(sym->Hunk);
  523.         size = (sym->Value + 3) & ~3;
  524.  
  525.         /*printf("CommonSymbolResolve: offset=%d size=%d %.*s\n", hunk->Bytes, size, len * 4, scan);*/
  526.  
  527.         SetSymbol(sym, hunk, hunk->Bytes, 1);
  528.         hunk->Bytes += size;
  529.         hunk->TotalBytes += size;
  530.     }
  531.     }
  532.     return(0);
  533. }
  534.  
  535. /*
  536.  *  CNT
  537.  *
  538.  *  This routine returns a dummy 0 always.  This routine updates the
  539.  *  the HunkListNode's CntReloc32 for 32 bit Reloc32 references.  We are
  540.  *  counting the number of relocs required for this hunk to allocate the master
  541.  *  reloc array.
  542.  *
  543.  *  This routine also handles Reloc16 and Reloc8's
  544.  */
  545.  
  546. int
  547. HunkExtSymCNT(Hunk *hunk, ubyte type, ulong len, ulong *scan)
  548. {
  549.     Sym *sym;
  550.  
  551.     if (type == 129) {
  552.     if ((sym = FindSymbol(scan, len)) != NULL) {
  553.         Hunk *destHunk;
  554.         long hunkNo;
  555.  
  556.         if (sym->Type == 2)
  557.         return(0);
  558.  
  559.         if ((destHunk = sym->Hunk) != NULL) {
  560.         hunkNo = destHunk->HX->FinalHunkNo;
  561.         if (hunkNo < 0 || hunkNo >= NumExtHunks)
  562.             cerror(EFATAL_RELOC_NOEXIST_HUNK, hunkNo, NumExtHunks);
  563.         if (sym->Type == 1)    /*  32 bit relocatable def */
  564.             hunk->HL->CntReloc32[hunkNo] += FromMsbOrder(scan[len]);
  565.         return(0);
  566.         }
  567.     }
  568.     cerror(EERROR_UNDEF_SYM, len*4, scan, hunk->Module->Node.ln_Name);
  569.     } else if (type == 131 || type == 132 || type == 134 || type == 135) {     /*  16dr,pc 8pc, 32pc    */
  570.     if ((sym = FindSymbol(scan, len)) != NULL) {
  571.         Hunk *destHunk = sym->Hunk;     /*  might be NULL         */
  572.         long hunkNo;
  573.         long n;
  574.         ulong *newScan = scan + len;
  575.  
  576.         if (destHunk) {
  577.         hunkNo = destHunk->HX->FinalHunkNo;
  578.         if (hunkNo < 0 || hunkNo >= NumExtHunks)
  579.             cerror(EFATAL_RELOC_NOEXIST_HUNK, hunkNo, NumExtHunks);
  580.         }
  581.         if (destHunk || sym->Type == 2) {
  582.         long destOff = 0;
  583.  
  584.         if (sym->Type != 2) {            /*    DATA symbol */
  585.             destOff = destHunk->Offset;
  586.             if (destHunk->HL != destHunk->HX)
  587.             destOff += destHunk->HX->FinalSize;
  588.         }
  589.         if ((n = FromMsbOrder(*newScan)) != 0) {
  590.             char *dbase = (char *)hunk->Data;
  591.             ulong dlen = hunk->Bytes;
  592.  
  593.             /*
  594.              *    relocate each 8/16 bit PC relative reference
  595.              */
  596.  
  597.             for (++newScan; n--; ++newScan) {
  598.             ulong doff = FromMsbOrder(*newScan);
  599.             long pcrel = 0;
  600.  
  601.             if (doff >= dlen)   /*    illegal or jump table reloc */
  602.                 continue;
  603.             switch(type) {
  604.             case 134:   /*    16 bit data-base relative reloc (NOT pcrel) */
  605.                 dbprintf(2, ("ext sym t=%d reloc16D %s@%ld(%ld) to %s@%ld\n", sym->Type, HunkToStr(hunk), doff, FromMsbOrderShort(*(short *)(dbase + doff)), HunkToStr(destHunk), sym->Value));
  606.                 switch(sym->Type) {
  607.                 case 2:    /*  ABS symbol    */
  608.                 pcrel = FromMsbOrderShort(*(short *)(dbase + doff)) + sym->Value;
  609.                 break;
  610.                 case 1:    /*  DATA symbol */
  611.                 pcrel = (destOff + sym->Value + FromMsbOrderShort(*(short *)(dbase + doff))) - 32766;
  612.                 if ((destHunk->Flags & HF_SMALLDATA) == 0)
  613.                     cerror(EERROR_A4REL_TO_FAR_OBJECT, sym->SymLen, sym->SymName, HunkToStr(destHunk), HunkToStr(hunk));
  614.                 break;
  615.                 default:
  616.                 cerror(EERROR_RELOC_ILLEGAL_SYM, sym->Type);
  617.                 break;
  618.                 }
  619.                 if (pcrel < -32768 || pcrel > 32767)
  620.                 cerror(EERROR_RELOC16DATA_SYM_RANGE, pcrel, sym->SymLen, sym->SymName, HunkToStr(hunk));
  621.                 *(short *)(dbase + doff) = ToMsbOrderShort(pcrel);
  622.                 break;
  623.             case 132:   /*    8 bit reloc */
  624.                 dbprintf(2, ("ext sym t=%d reloc08 %s@%ld(%ld) to %s@%ld\n", sym->Type, HunkToStr(hunk), doff, *(char *)(dbase + doff), HunkToStr(destHunk), sym->Value));
  625.                 switch(sym->Type) {
  626.                 case 2:
  627.                 pcrel = *(char *)(dbase + doff) + sym->Value;
  628.                 break;
  629.                 case 1:
  630.                 pcrel = (destOff + sym->Value + *(char *)(dbase + doff)) - (hunk->Offset + doff);
  631.                 break;
  632.                 default:
  633.                 cerror(EERROR_RELOC_ILLEGAL_SYM, sym->Type);
  634.                 break;
  635.                 }
  636.                 if (pcrel < -128 || pcrel > 127)
  637.                 cerror(EERROR_RELOC8_RANGE, pcrel);
  638.                 *(ubyte *)(dbase + doff) = pcrel;
  639.                 break;
  640.             case 131:   /*    16 bit pc-relative reloc */
  641.                 dbprintf(2, ("ext sym t=%d reloc16pc %s@%ld(%ld) to %s@%ld\n", sym->Type, HunkToStr(hunk), doff, FromMsbOrderShort(*(short *)(dbase + doff)), HunkToStr(destHunk), sym->Value));
  642.  
  643.                 switch(sym->Type) {
  644.                 case 2:    /*  Absolute Symbol */
  645.                 pcrel = FromMsbOrderShort(*(short *)(dbase + doff)) + sym->Value;
  646.                 break;
  647.                 case 1:    /*  Data Symbol     */
  648.                 if (hunk->HL != destHunk->HX) {
  649.                     if (AbsWordOpt) {
  650.                     pcrel = (destOff + sym->Value + FromMsbOrderShort(*(short *)(dbase + doff))) + WordBaseAddr;
  651.                     } else {
  652.                     cerror(EERROR_PCREL_RELOC_TO_DATA,
  653.                         hunk->Module->Node.ln_Name,
  654.                         hunk->Node.ln_Name,
  655.                         sym->SymLen, sym->SymName
  656.                     );
  657.                     }
  658.                 } else {
  659.                     pcrel = (destOff + sym->Value + FromMsbOrderShort(*(short *)(dbase + doff))) - (hunk->Offset + doff);
  660.                 }
  661.                 break;
  662.                 default:
  663.                 cerror(EERROR_RELOC_ILLEGAL_SYM, sym->Type);
  664.                 break;
  665.                 }
  666.                 if (pcrel < -32768 || pcrel > 32767)
  667.                 cerror(EERROR_RELOC16DATA_SYM_RANGE, pcrel, sym->SymLen, sym->SymName, HunkToStr(hunk));
  668.                 *(short *)(dbase + doff) = ToMsbOrderShort(pcrel);
  669.                 break;
  670.             case 135:   /*    32 bit pc-relative reloc */
  671.                 dbprintf(2, ("ext sym t=%d reloc32pc %s@%ld(%ld) to %s@%ld\n", sym->Type, HunkToStr(hunk), doff, FromMsbOrder(*(long *)(dbase + doff)), HunkToStr(destHunk), sym->Value));
  672.  
  673.                 switch(sym->Type) {
  674.                 case 2:    /*  Absolute Symbol    */
  675.                 pcrel = FromMsbOrder(*(long *)(dbase + doff)) + sym->Value;
  676.                 break;
  677.                 case 1:    /*  std label Symbol    */
  678.                 pcrel = (destOff + sym->Value + FromMsbOrder(*(long *)(dbase + doff))) - (hunk->Offset + doff);
  679.                 break;
  680.                 default:
  681.                 cerror(EERROR_RELOC_ILLEGAL_SYM, sym->Type);
  682.                 break;
  683.                 }
  684.                 *(long *)(dbase + doff) = ToMsbOrder(pcrel);
  685.                 break;
  686.             default:
  687.                 break;
  688.             }
  689.             }
  690.         }
  691.         return(0);
  692.         }
  693.     }
  694.     cerror(EERROR_UNDEF_SYM, len*4, scan, hunk->Module->Node.ln_Name);
  695.     } else if (type == RESERVED_PCJMP_TYPE) {
  696.     if ((sym = FindSymbol(scan, len)) != NULL) {
  697.         Hunk *destHunk;
  698.         long hunkNo;
  699.  
  700.         if ((destHunk = sym->Hunk) != NULL) {
  701.         hunkNo = destHunk->HX->FinalHunkNo;
  702.         if (hunkNo < 0 || hunkNo >= NumExtHunks)
  703.             cerror(EFATAL_RANGE_HUNK, hunkNo, NumExtHunks);
  704.         if (sym->Type != 1)    /*  32 bit relocatable def */
  705.             cerror(EFATAL_PC_REL_ILLEGAL_SYMBOL, sym->Type);
  706.         ++hunk->HL->CntReloc32[hunkNo];
  707.         return(0);
  708.         }
  709.     }
  710.     cerror(EERROR_UNDEF_SYM, len*4, scan, hunk->Module->Node.ln_Name);
  711.     }
  712.     return(0);
  713. }
  714.  
  715. /*
  716.  *  RUN
  717.  *
  718.  *  This routine returns a dummy value, 0.  This routine modifies the hunk
  719.  *  data appropriately for a reloc32.
  720.  */
  721.  
  722. int
  723. HunkExtSymRUN(Hunk *hunk, ubyte type, ulong len, ulong *scan)
  724. {
  725.     Sym *sym;
  726.     Hunk *destHunk;
  727.     long hunkNo = 0;
  728.  
  729.     if (type != 129 && type != RESERVED_PCJMP_TYPE)
  730.     return(0);
  731.     if ((sym = FindSymbol(scan, len)) == NULL)
  732.     return(0);
  733.  
  734.     if ((destHunk = sym->Hunk) != NULL) {
  735.     hunkNo = destHunk->HX->FinalHunkNo;
  736.     if (hunkNo < 0 || hunkNo >= NumExtHunks)
  737.         cerror(EFATAL_EXTSYM_RELOC);
  738.     }
  739.  
  740.     /*
  741.      *    Special case... single relocation jump table beyond end of
  742.      *    hunk->Bytes.
  743.      *
  744.      *    if scan[len] > 1 we actually only do one... see 'jump.c'.  We
  745.      *    converted N pc-relative jumps to external jumps.
  746.      */
  747.  
  748.     if (type == RESERVED_PCJMP_TYPE) {
  749.     SanityCheck(32);
  750.     if (destHunk == NULL)
  751.         return(0);
  752.     SanityCheck(33);
  753.     if (FromMsbOrder(scan[len])) {            /*    # of relocs */
  754.         long bas = hunk->HL->CpyReloc32[hunkNo];
  755.         long n = FromMsbOrder(scan[len+1]) - hunk->Bytes;     /*    first reloc */
  756.  
  757.         hunk->HL->ExtReloc32[hunkNo][bas] = ToMsbOrder(hunk->Offset + hunk->Bytes + n);
  758.         ++bas;
  759.         hunk->HL->CpyReloc32[hunkNo] = bas;
  760.  
  761.         if (n < 0 || n >= hunk->TotalBytes - hunk->Bytes)
  762.         cerror(ESOFT_JUMP_TABLE);
  763.  
  764.         *(long *)((char *)hunk->JmpData + n) = ToMsbOrder(destHunk->Offset + sym->Value);
  765.     }
  766.     SanityCheck(34);
  767.     return(0);
  768.     }
  769.  
  770.     /*
  771.      *    ABS symbols need no destination hunk.
  772.      */
  773.  
  774.     if (destHunk == NULL && sym->Type != 2)
  775.     return(0);
  776.  
  777.     /*
  778.      *    copy relocation info
  779.      */
  780.  
  781.     SanityCheck(35);
  782.     if (sym->Type == 1) {    /*  only if relocatable def    */
  783.     long bas = hunk->HL->CpyReloc32[hunkNo];
  784.     long fnl = bas + FromMsbOrder(scan[len]);
  785.  
  786. #ifdef NOTDEF
  787.     printf("HUNK %s hunkno %d vs %d NUMEXT %d\n", HunkToStr(hunk), hunk->HunkNo, hunkNo, NumExtHunks);
  788.     printf("BAS %d FNL %d CNT %d\n", bas, fnl, hunk->HL->CntReloc32[hunkNo]);
  789.     printf("LEN=%d SCAN[LEN]= %d relocs OFF=%d\n", len, scan[len], hunk->Offset);
  790. #endif
  791.  
  792.     if (fnl > hunk->HL->CntReloc32[hunkNo])
  793.         cerror(EFATAL_EXTSYM_RELOC);
  794.     copy_reloc(scan + len + 1, hunk->HL->ExtReloc32[hunkNo] + bas, FromMsbOrder(scan[len]), hunk->Offset);
  795.  
  796.     hunk->HL->CpyReloc32[hunkNo] = fnl;
  797.     }
  798.  
  799.     SanityCheck(36);
  800.     /*
  801.      *    handle relocation
  802.      */
  803.  
  804.     if (FromMsbOrder(scan[len])) {
  805.     ulong n = FromMsbOrder(scan[len]);
  806.     ulong *newScan;
  807.     char *dbase = (char *)hunk->Data;
  808.     ulong dlen = hunk->Bytes;
  809.     ulong destOff = 0;
  810.  
  811.     if (sym->Type != 2) {
  812.         destOff = destHunk->Offset;
  813.         if (destHunk->HL != destHunk->HX)
  814.         destOff += destHunk->HX->FinalSize;
  815.     }
  816.  
  817.     if ((ResOpt || PIOpt) && sym->Type != 2) {
  818.         if (destHunk->Node.ln_Type == NT_BSS && !AbsWordOpt)
  819.         cerror(EERROR_ABS_REFS_DATA_BSS, sym->SymLen, sym->SymName);
  820.         if (destHunk->Node.ln_Type == NT_DATA && sym != DataBasSym && !AbsWordOpt)
  821.         cerror(EERROR_ABS_REFS_DATA_BSS, sym->SymLen, sym->SymName);
  822.     }
  823.  
  824.     for (newScan = scan + len + 1; n--; ++newScan) {
  825.         ulong doff = FromMsbOrder(*newScan);
  826.         long rval = 0;
  827.  
  828.         dbprintf(3, ("ext sym t=%d reloc32 %s@%ld to %s@%ld (%.*s)\n", sym->Type, HunkToStr(hunk), doff, HunkToStr(destHunk), sym->Value, sym->SymLen, sym->SymName));
  829.  
  830.         if (doff >= dlen)    /*  illegal or jump table */
  831.         continue;
  832.         if (doff & 1)
  833.         cerror(EFATAL_RELOC_WORD_ALIGN);
  834.  
  835.         switch(sym->Type) {
  836.         default:
  837.         cerror(EFATAL_RELOC_ILLEGAL_SYM, sym->Type);
  838.         break;
  839.         case 2:        /*    abs  */
  840.         rval = FromMsbOrder(*(ulong *)(dbase + doff)) + sym->Value;
  841.         break;
  842.         case 1:        /*    def  */
  843.         rval = destOff + FromMsbOrder(*(ulong *)(dbase + doff)) + sym->Value;
  844.         break;
  845.         }
  846.         *(ulong *)(dbase + doff) = ToMsbOrder(rval);
  847.     }
  848.     }
  849.     SanityCheck(37);
  850.     return(0);
  851. }
  852.  
  853. void
  854. IllegalHunk(short er_flag, Hunk *hunk)
  855. {
  856.     if (hunk)
  857.     cerror(er_flag | EILLEGAL_HUNK, hunk, hunk->Node.ln_Type, hunk->Module->Node.ln_Name);
  858.     else
  859.     cerror(er_flag | EILLEGAL_HUNK, NULL, -1, "???");
  860. }
  861.  
  862.